﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.Net;

namespace TcpProxy
{
    public class BlockingStreamReader
    {
        public enum Endianness
        {
            LittleIntel,
            BigMotorola
        }

        bool _flipEndian;
        PipeStream _stream;

        public int Offset { get; internal set; }

        public BlockingStreamReader(PipeStream stream, Endianness endian)
        {
            Offset = 0;

            _stream = stream;
            _flipEndian =
                (((BitConverter.IsLittleEndian) && (endian == Endianness.BigMotorola)) ||
                ((!BitConverter.IsLittleEndian) && (endian == Endianness.LittleIntel)));
        }

        public byte ReadByte()
        {
            //can convert because it will block until there is a byte
            byte b = (byte)_stream.ReadByte();
            Offset++;
            return b;
        }

        public byte[] ReadBytes(int len)
        {
            if (len == 0) return new byte[1];

            byte[] buff = new byte[len];
            int ofs = 0;

            while (ofs < len)
            {
                int ret = _stream.Read(buff, ofs, len - ofs);
                ofs += ret;
            }

            Offset += len;
            return buff;
        }

        public short ReadShort()
        {
            byte[] b = ReadBytes(2);

            if (_flipEndian)
                return IPAddress.HostToNetworkOrder(BitConverter.ToInt16(b, 0));
            else
                return BitConverter.ToInt16(b, 0);
        }

        public int ReadInt()
        {
            byte[] b = ReadBytes(4);

            if (_flipEndian)
                return IPAddress.HostToNetworkOrder(BitConverter.ToInt32(b, 0));
            else
                return BitConverter.ToInt32(b, 0);
        }

        public long ReadLong()
        {
            byte[] b = ReadBytes(8);

            if (_flipEndian)
                return IPAddress.HostToNetworkOrder(BitConverter.ToInt64(b, 0));
            else
                return BitConverter.ToInt64(b, 0);
        }

        public Single ReadSingle()
        {
            byte[] b = ReadBytes(4);

            if (_flipEndian) Array.Reverse(b);

            return BitConverter.ToSingle(b, 0);
        }

        public Double ReadDouble()
        {
            byte[] b = ReadBytes(8);

            if (_flipEndian) Array.Reverse(b);

            return BitConverter.ToDouble(b, 0);
        }

    }
}
